import ezdxf
import pandas as pd
import os


def draw_table_block(msp, table_data, insert_point, block_name):
    doc = msp.doc
    if block_name in doc.blocks:
        doc.blocks.delete_block(block_name)

    block = doc.blocks.new(name=block_name)

    rows, cols = table_data.shape

    base_cell_width = 600
    base_cell_height = 200
    extra_height_per_line = 170
    max_chars_per_line = 12
    max_lines_without_widening = 1
    text_height = 120

    col_widths = [base_cell_width for _ in range(cols)]
    cell_lines = [[[] for _ in range(cols)] for _ in range(rows)]
    row_heights = [base_cell_height for _ in range(rows)]

    # 第一轮：根据默认列宽计算每格行数、初始行高
    for row in range(rows):
        max_lines_in_row = 1
        for col in range(cols):
            content = str(table_data.iat[row, col])
            lines = [content[i:i+max_chars_per_line] for i in range(0, len(content), max_chars_per_line)]
            cell_lines[row][col] = lines
            if len(lines) > max_lines_in_row:
                max_lines_in_row = len(lines)
        if max_lines_in_row > max_lines_without_widening:
            row_heights[row] = base_cell_height + (max_lines_in_row - max_lines_without_widening) * extra_height_per_line

    # 第二轮：对列宽不足的列尝试扩展
    for col in range(cols):
        for row in range(rows):
            content = str(table_data.iat[row, col])
            if len(content) <= max_chars_per_line * max_lines_without_widening:
                continue
            # 扩展逻辑
            cur_chars_per_line = max_chars_per_line
            new_col_width = base_cell_width
            while True:
                cur_chars_per_line += 5
                new_col_width += 400
                lines = [content[i:i+cur_chars_per_line] for i in range(0, len(content), cur_chars_per_line)]
                if len(lines) <= max_lines_without_widening:
                    col_widths[col] = new_col_width
                    cell_lines[row][col] = lines
                    break

        # 所有行中该列的文字重新划分
        for row in range(rows):
            content = str(table_data.iat[row, col])
            cur_chars_per_line = col_widths[col] // 100
            lines = [content[i:i+cur_chars_per_line] for i in range(0, len(content), cur_chars_per_line)]
            cell_lines[row][col] = lines
            line_count = len(lines)
            height = base_cell_height + max(0, line_count - max_lines_without_widening) * extra_height_per_line
            if height > row_heights[row]:
                row_heights[row] = height

    # 第三步：开始绘制表格
    y_cursor = 0
    for row in range(rows):
        row_height = row_heights[row]
        x_cursor = 0
        for col in range(cols):
            col_width = col_widths[col]
            x = x_cursor
            y = -y_cursor

            # 画边框
            block.add_lwpolyline([
                (x, y),
                (x + col_width, y),
                (x + col_width, y - row_height),
                (x, y - row_height),
                (x, y)
            ])

            # 插入文字
            lines = cell_lines[row][col]
            multiline_text = "\n".join(lines)
            mtext = block.add_mtext(multiline_text, dxfattribs={"char_height": text_height})
            mtext.dxf.insert = (x + 20, y - 20)
            mtext.dxf.width = col_width - 40

            x_cursor += col_width
        y_cursor += row_height

    # 插入 block 实例
    msp.add_blockref(block_name, insert_point)


def delete_block_refs_get_positions(msp, block_name):
    positions = []
    for entity in list(msp):
        if entity.dxftype() == "INSERT" and entity.dxf.name == block_name:
            positions.append(entity.dxf.insert)
            msp.delete_entity(entity)
    return positions


def delete_block_definition(doc, block_name):
    if block_name in doc.blocks:
        doc.blocks.delete_block(block_name, safe=False)
        print(f"✅ 已删除块定义: {block_name}")
    else:
        print(f"⚠️ 块 '{block_name}' 不存在，跳过删除定义")


def replace_blocks_with_excel_tables(dxf_path, excel_path, doc,msp):
    xls = pd.ExcelFile(excel_path)

    block_names = set(doc.blocks.block_names())

    for sheetname in xls.sheet_names:
        matched_blocks = [name for name in block_names if sheetname in name]
        if not matched_blocks:
            print(f"未找到包含 sheet 名称 '{sheetname}' 的块，跳过")
            continue

        df = xls.parse(sheetname).fillna(' ')


        # ✅ 添加列名作为第一行
        df_with_header = pd.concat([
            pd.DataFrame([df.columns.tolist()], columns=df.columns),
            df
        ], ignore_index=True)

        print(f"📄 正在替换块: {matched_blocks} 对应 sheet: {sheetname}")

        for block_name in matched_blocks:
            positions = delete_block_refs_get_positions(msp, block_name)
            print(f"📌 找到 {len(positions)} 个引用位置")

            delete_block_definition(doc, block_name)

            for pos in positions:
                draw_table_block(msp, df_with_header, pos, block_name)

def replace_blocks_with_excel_paths(dxf_file, excel_paths, output_dxf):
    """
    替换 DXF 文件中的块为 Excel 表格。
    :param dxf_file: 输入的 DXF 文件路径
    :param excel_file: 包含表格数据的 Excel 文件路径
    :param output_dxf: 输出的 DXF 文件路径
    """
    doc = ezdxf.readfile(dxf_file)
    msp = doc.modelspace()
    for excel_file in excel_paths:
        if not os.path.exists(excel_file):
            print(f"⚠️ Excel 文件不存在: {excel_file}")
            continue
        print(f"正在处理 Excel 文件: {excel_file}")
        # 替换块为 Excel 表格
        replace_blocks_with_excel_tables(dxf_file, excel_file, doc, msp)
    doc.saveas(output_dxf)

def update_design_quantity(target_name, excel_paths):
    update_path = []
    for path in excel_paths:
        try:
            xls = pd.ExcelFile(path, engine='openpyxl')
            for sheet_name in xls.sheet_names:
                df = pd.read_excel(path, sheet_name=sheet_name, engine='openpyxl')
                columns = df.columns.astype(str)

                # 判断是否是设备清单表
                if '设备型号' in columns and '设备厂家' in columns and '名称' in columns and '设计数量' in columns:
                    updated = False
                    for idx, name in df['名称'].items():
                        if str(name).strip() == target_name:
                            # 当前值
                            current_value = str(df.at[idx, '设计数量']).strip()
                            # 处理空格或非数字情况
                            if current_value == '' or current_value.isspace():
                                new_value = 1
                            else:
                                try:
                                    new_value = int(float(current_value)) + 1
                                except ValueError:
                                    new_value = 1  # 如果是非数字，也设为1
                            # 更新值
                            df.at[idx, '设计数量'] = new_value
                            updated = True
                            print(f"更新：文件 {path}，sheet {sheet_name}，第 {idx + 2} 行 ‘设计数量’ 设置为 {new_value}")
                            update_path.append(path)
                    if updated:
                        # 保存回 Excel 原文件
                        with pd.ExcelWriter(path, engine='openpyxl', mode='a', if_sheet_exists='replace') as writer:
                            df.to_excel(writer, sheet_name=sheet_name, index=False)
        except Exception as e:
            print(f"处理文件 {path} 时出错：{e}")
    return update_path


# 示例调用
if __name__ == "__main__":
    dxf_file = r"E:\cadsecond-processing\drawingLibrary\嘉兴海宁全1.dxf"
    # excel_file = r"D:/设计院项目\cadsecond-processing\retrieve_folder\远端机房设备平面布置图_5_20250717_101953_693_tables.xlsx"
    output_dxf = r"E:\cadsecond-processing\output.dxf"
    target_device_name = "BBU机框"
    excel_paths = [r'E:\cadsecond-processing\retrieve_folder\海宁长安皮毛市场汇聚机房近端机房设备平面布置图_3_20250717_101946_997_tables.xlsx',
                   r'E:\cadsecond-processing\retrieve_folder\海宁长安皮毛市场汇聚机房线缆路由及GPS天线安装示意图_4_20250717_101950_344_tables.xlsx',
                   r'E:\cadsecond-processing\retrieve_folder\远端机房设备平面布置图_5_20250717_101953_693_tables.xlsx',
                   r'E:\cadsecond-processing\retrieve_folder\远端机房线缆路由图_6_20250717_101957_142_tables.xlsx',
                   r'E:\cadsecond-processing\retrieve_folder\远端基站天馈安装示意图_7_20250717_102000_569_tables.xlsx'
                   ]
    # 更新设计数量
    l = update_design_quantity(target_device_name, excel_paths)
    print(f"更新的 Excel 文件路径: {l}")
    # 替换 DXF 中的块为 Excel 表格
    replace_blocks_with_excel_paths(dxf_file, l, output_dxf)
